package com.grad.webstudy.service.impl;

import ch.ethz.ssh2.Connection;
import com.grad.webstudy.constants.LinuxConstants;
import com.grad.webstudy.context.UserContext;
import com.grad.webstudy.dao.CodeDao;
import com.grad.webstudy.enums.CodeEnum;
import com.grad.webstudy.enums.DockerImagesEnum;
import com.grad.webstudy.enums.ExceptionEnums;
import com.grad.webstudy.exceptions.CustomException;
import com.grad.webstudy.model.Code;
import com.grad.webstudy.model.User;
import com.grad.webstudy.service.CodeService;
import com.grad.webstudy.utils.LinuxUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * @Description:
 * @Author: zjf
 * @Date: 2020/1/15 11:27.
 */
@Service
@Transactional
public class CodeServiceImpl implements CodeService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private CodeDao codeDao;


    @Override
    public String runCode(Code code) {
//        User loginUser = UserContext.getLoginUser();
//        User loginUser = new User();
//        loginUser.setId(13);
        String result = "";
        int codeNumber = code.getCodeNumber();//获取代码的编号
        String codeContent = code.getCodeContent();
//        code.setUserId(loginUser.getId());
//        codeDao.saveCode(code) > 0
        if (true) {

            result = runCodeOnServer(codeNumber, codeContent);
            logger.info(result);
            result = result.substring(LinuxConstants.IMAGE_ID_LENGTH + 1, result.length());
            return result;
        } else {

            throw new CustomException(ExceptionEnums.CUSTOM_ERROR.getCode(),
                    "保存代码出错");
        }

    }


    /**
     * 在服务器上执行代码
     *
     * @param codeNumber
     * @param codeContent
     * @return
     */
    private String runCodeOnServer(int codeNumber, String codeContent) {

        String result = "";


        String imageName = DockerImagesEnum.getValue(codeNumber);//镜像名称

        String type = CodeEnum.getType(codeNumber).toLowerCase();//语言类型

        String suffix = CodeEnum.getSuffix(codeNumber);//语言后缀
        String filePath = LinuxConstants.FILE_PREFIX + type + LinuxConstants.FILE_SUFFIX;//服务器对应的每种编程语言的DockerFile以及java文件的保存位置


        String path = "D://Hello." + suffix;//本地文件,缓存文件
        byte[] sourceByte = codeContent.getBytes();
        if (null != sourceByte) {
            try {
                File file = new File(path);        //文件路径（路径+文件名）
                if (!file.exists()) {    //文件不存在则创建文件，先创建目录
                    File dir = new File(file.getParent());
                    dir.mkdirs();
                    file.createNewFile();
                }
                FileOutputStream outStream = new FileOutputStream(file);    //文件输出流用于将数据写入文件
                outStream.write(sourceByte);
                outStream.close();    //关闭文件输出流

                if (LinuxUtils.FtpUtils.existFile(filePath)) {
                    LinuxUtils.FtpUtils.deleteFile(filePath, "Hello." + suffix);
                }

                LinuxUtils.FtpUtils.uploadFile(filePath, "Hello." + suffix, path);//上传代码文件到服务器上


                // 连接Linux执行shell命令
                Connection conn = LinuxUtils.login(LinuxConstants.IP,
                        LinuxConstants.USERNAME,
                        LinuxConstants.PASSWORD);
                result = LinuxUtils.execute(conn, "cd " + filePath + ";" +
                        "docker build -qt " + imageName + " .;" +
                        "docker run " + imageName);

                file.delete();//删除文件
            } catch (IOException e) {
                e.printStackTrace();
                throw new CustomException(ExceptionEnums.CUSTOM_ERROR.getCode(),"IO异常");
            } catch (Exception e) {
                e.printStackTrace();
                throw new CustomException(ExceptionEnums.CUSTOM_ERROR.getCode(),e.getMessage());
            }
        }


        return result;
    }

    @Override
    public List<Code> findCode() {
        User loginUser = UserContext.getLoginUser();
        return codeDao.findCode(loginUser.getId());
    }
}
